package space.jamestang.simpleci.runner

import space.jamestang.simpleci.config.ConfigChecker
import space.jamestang.simpleci.globalLogger
import space.jamestang.simpleci.schema.BuildTool
import space.jamestang.simpleci.schema.Environment
import space.jamestang.simpleci.schema.Project
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader

@Suppress("unused")
class Runner {

    private constructor()

    private lateinit var buildTool: BuildTool
    private lateinit var project: Project



    companion object Builder{

        fun build(project: Project, buildTool: BuildTool): Runner {

            val runner = Runner()

            runner.project = project
            runner.buildTool = buildTool

            return runner
        }
    }

    fun run() {

        project.initializeProject(project)

        project.buildCommand.forEach { cmd ->
            val executor = Executor("${ConfigChecker.config.reposDir}/${project.name}", project.environment, *cmd.command.toTypedArray())
            executor.execute()
        }
    }


}

internal class Executor(baseDir: String?, environment: List<Environment>?, vararg commands: String){

    val osType: String = System.getProperty("os.name")



    private var action: ProcessBuilder = if (osType.startsWith("Windows")) {
        ProcessBuilder("cmd", "/c", *commands)
    } else {
        ProcessBuilder("bash", *commands)
    }

    init {
        if (baseDir != null) action.directory(File(baseDir))
       if (environment != null){
            action.environment().putAll(environment.associate { it.name to it.value })
       }else action.environment().putAll(System.getenv())

    }


    fun execute(): Int {

        val process = action.start()

        BufferedReader(InputStreamReader(process.errorStream)).use { br ->
            var line: String?
            while (br.readLine().also { line = it } != null) {
                globalLogger.error(line)
            }
        }

        BufferedReader(InputStreamReader(process.inputStream)).use { br ->
            var line: String?
            while (br.readLine().also { line = it } != null) {
                globalLogger.info(line)
            }
        }


        val exitCode = process.waitFor()

        return exitCode
    }
}